home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
gc
/
GCdirty.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-06
|
8KB
|
272 lines
/* begincopyright
Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
Parts of this software were derived from code bearing the copyright notice:
Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
This material may be freely distributed, provided this notice is retained.
This material is provided as is, with no warranty expressed or implied.
Use at your own risk.
endcopyright */
# include "xr/GCPrivate.h"
# include "xr/GCVirtualDirty.h"
/* Boehm, May 15, 1990 2:00:28 pm PDT */
/*
* contains:
* GC_clear_dirty_bits() - reset all pages to clean. Doesn't affect
* GC_dirty_bits array.
* GC_set_dirty_bits() - Set all pages to dirty status. Doesn't affect
* GC_dirty_bits array.
* GC_clear_some_dirty_bits(start,limit) - same, but only for a specified
* region of the heap.
* GC_get_dirty_bits() - Set GC_dirty bits to reflect which blocks have
* been touched.
* GC_get_and_clear_dirty_bits() - Set GC_dirty_bits and atomically
* reset pages to clean.
* GC_propagate_dirty_bits() - propagate dirty bits to all blocks covered
* by large dirty objects.
*
* Boehm, September 28, 1990 2:51:21 pm PDT
*/
# if VD_PAGE_SIZE != HBLKSIZE
--> We assume VD_PAGE_SIZE == HBLKSIZE
# endif
/* Clear dirty bits for all pages in the specified range */
void GC_clear_some_dirty_bits(start, limit)
char * start;
char * limit;
{
# ifdef DIRTY_BITS
struct XR_VDBufRep VDArgBuf;
int errno;
/* Set up memory region descriptor */
VDArgBuf.vdb_buf = (char *) 0; /* dirty bit table */
VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)start;
VDArgBuf.vdb_seg.seg_bytes = limit - start;
/* Issue the call */
errno = -XR_VDOp(XR_VDOpCodeSetClean, 1, &VDArgBuf);
if (errno > 0) {
GC_iprintf("Failed to clear dirty bits, errno = %d\n", errno);
}
# endif
}
/* Clear dirty bits for all entries in the heap and data segment */
void GC_clear_dirty_bits()
{
# ifdef DIRTY_BITS
/* Make sure VD_base is initialized */
XR_StartVD();
GC_clear_some_dirty_bits(VD_base, GC_heaplim);
# endif
}
/* Set dirty bits for all pages in the heap and data segment */
void GC_set_dirty_bits()
{
# ifdef DIRTY_BITS
struct XR_VDBufRep VDArgBuf;
int errno;
/* Make sure VD_base is initialized */
XR_StartVD();
/* Set up memory region descriptor */
VDArgBuf.vdb_buf = (char *) 0; /* dirty bit table */
VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)VD_base;
VDArgBuf.vdb_seg.seg_bytes = GC_heaplim - VD_base;
/* Issue the call */
errno = -XR_VDOp(XR_VDOpCodeSetDirty, 1, &VDArgBuf);
if (errno > 0) {
GC_iprintf("Failed to set dirty bits, errno = %d\n", errno);
GC_abort("Failed to set dirty bits\n");
}
# endif
}
/* Set GC_dirty_bits array entries for each page. */
void GC_get_dirty_bits()
{
register unsigned long limit;
register unsigned long index;
# ifdef DIRTY_BITS
register unsigned long offset;
register struct hblk * h;
register word * p;
char map_entry;
struct XR_VDBufRep VDArgBuf;
int errno;
# ifdef PRINTSTATS
long n_clean = 0;
long n_dirty = 0;
# endif
/* Make sure VD_base is initialized */
XR_StartVD();
/* Set up memory region descriptor */
VDArgBuf.vdb_buf = (char *) GC_dirty_bits; /* dirty bit table */
VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)VD_base;
VDArgBuf.vdb_seg.seg_bytes = GC_heaplim - VD_base;
/* Issue the call */
limit = divHBLKSZ(GC_heaplim - VD_base);
errno = -XR_VDOp(XR_VDOpCodeNOOP, 1, &VDArgBuf);
if (errno > 0) {
GC_iprintf("Failed to retrieve dirty bits, errno = %d\n", errno);
for (index = 0;
index < limit; index++) {
GC_dirty_bits[index] = 1;
}
}
# ifdef PRINTSTATS
offset = divHBLKSZ(GC_heapstart - VD_base);
for(index = offset;
index < limit; index++) {
if (hblkmap[index-offset] != HBLK_INVALID) {
if (GC_dirty_bits[index]) {
n_dirty++;
} else {
n_clean++;
}
}
}
# endif
# ifdef PRINTSTATS
GC_printf("Found %d clean, %d dirty pages\n", n_clean, n_dirty);
# endif
# else
/* Make sure VD_base is initialized */
XR_StartVD();
limit = divHBLKSZ(GC_heaplim - VD_base);
for (index = 0;
index < limit; index++) {
GC_dirty_bits[index] = 1;
}
# endif
}
/* Set GC_dirty_bits array entries for each page and clear dirty bits. */
void GC_get_and_clear_dirty_bits()
{
# ifdef DIRTY_BITS
register struct hblk * h;
register word * p;
char map_entry;
register unsigned long index;
struct XR_VDBufRep VDArgBuf;
int errno;
# ifdef PRINTSTATS
register unsigned long offset;
long n_clean = 0;
long n_dirty = 0;
# endif
register unsigned long limit;
/* Make sure VD_base is initialized */
XR_StartVD();
/* Set up memory region descriptor */
VDArgBuf.vdb_buf = (char *) GC_dirty_bits; /* dirty bit table */
VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)VD_base;
VDArgBuf.vdb_seg.seg_bytes = GC_heaplim - VD_base;
/* Issue the call */
limit = divHBLKSZ(GC_heaplim - VD_base);
errno = -XR_VDOp(XR_VDOpCodeSetClean, 1, &VDArgBuf);
if (errno > 0) {
GC_iprintf("Failed to retrieve dirty bits, errno = %d\n", errno);
for (index = 0;
index < limit; index++) {
GC_dirty_bits[index] = 1;
}
}
# ifdef PRINTSTATS
offset = divHBLKSZ(GC_heapstart - VD_base);
for (index = offset;
index < limit; index++) {
if (hblkmap[index-offset] != HBLK_INVALID) {
if (GC_dirty_bits[index]) {
n_dirty++;
} else {
n_clean++;
}
}
}
# endif
# ifdef PRINTSTATS
GC_printf("Found %d clean, %d dirty pages - cleaned all\n",
n_clean, n_dirty);
# endif
# else
GC_get_dirty_bits();
# endif
}
/* Set dirty bit of first page of chunk if any of the continuation */
/* pages are dirty, and if the page contains composite objects. */
void GC_propagate_dirty_bits()
{
# ifdef DIRTY_BITS
register long index = 0;
register long offset = divHBLKSZ(GC_heapstart - VD_base);
register char dirty;
register unsigned long limit = divHBLKSZ(GC_heaplim - GC_heapstart);
dirty = 0;
for (index = limit - 1; index >= 0; index--) {
switch(hblkmap[index]) {
case HBLK_INVALID:
/* While we're chugging down the continuation pages,
we might get paused, and some other process might
set HBLK_INVALID. For example, a large block might
be explicitly freed.
*/
if (dirty && GC_running_exclusive) {
GC_iprintf("Corrupted hblkmap (%d)\n", index);
GC_abort("Corrupted hblkmap");
} else {
dirty = FALSE;
}
break;
case HBLK_VALID:
# ifdef SEPARATE_HEADERS
if (GC_headers[index] -> hbh_sz > 0) {
# else
if (hb_sz(GC_heapstart + HBLKSIZE * index) > 0) {
# endif
/* Composite */
GC_dirty_bits[index + offset] |= dirty;
}
dirty = 0;
break;
default:
dirty |= GC_dirty_bits[index + offset];
break;
}
}
# endif
/* otherwise everything is "dirty" to start with */
}